home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus Leser 19
/
Amiga Plus Leser CD 19.iso
/
Tools
/
Development
/
qstat25b
/
hcache.c
< prev
next >
Wrap
C/C++ Source or Header
|
2002-11-18
|
10KB
|
449 lines
/*
* qstat 2.4
* by Steve Jankowski
* steve@activesw.com
* http://www.activesw.com/people/steve/qstat.html
*
* Thanks to Per Hammer for the OS/2 patches (per@mindbend.demon.co.uk)
* Thanks to John Ross Hunt for the OpenVMS Alpha patches (bigboote@ais.net)
* Thanks to Scott MacFiggen for the quicksort code (smf@activesw.com)
*
* Inspired by QuakePing by Len Norton
*
* Copyright 1996,1997,1998,1999 by Steve Jankowski
*
* Licensed under the Artistic License, see LICENSE.txt for license terms
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "qstat.h"
#ifdef _ISUNIX
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif
#ifdef _WIN32
#include <winsock.h>
#endif
#ifdef __hpux
#define STATIC static
#else
#define STATIC
#endif
#ifndef INADDR_NONE
#define INADDR_NONE ~0
#endif
typedef struct _cache_entry {
unsigned long ipaddr;
char *hostname[5];
} cache_entry;
static cache_entry *hcache;
static int n_entry;
static int max_entry;
static char *last_filename;
static int n_changes;
static int debug;
static void write_file(FILE *file);
static cache_entry * init_entry( unsigned long ipaddr, char *hostname,
cache_entry *known);
static cache_entry * find_entry( unsigned long ipaddr);
static void free_entry( cache_entry *entry);
static cache_entry * validate_entry( cache_entry *entry);
static cache_entry * find_host_entry( char *hostname);
static void add_hostname( cache_entry *entry, const char *hostname);
int
hcache_open( char *filename, int update)
{
FILE *file;
char line[500], ipstr[500], hostname[500];
char *l;
int line_no, end;
unsigned long ip1, ip2, ip3, ip4, ipaddr;
cache_entry *entry;
file= fopen( filename, update?"r+":"r");
if ( file == NULL) {
if ( errno == ENOENT) {
fprintf( stderr, "Creating new host cache \"%s\"\n", filename);
last_filename= filename;
return 0;
}
perror( filename);
return -1;
}
last_filename= filename;
for ( line_no= 1; fgets( line, sizeof(line), file) != NULL; line_no++) {
if ( strlen(line) < 2)
continue;
if ( line[strlen(line)-1] != '\n') {
printf( "%d: line too long\n", line_no);
continue;
}
l= line;
while ( isspace( *l)) l++;
if ( *l == '#' || *l == '\0')
continue;
if ( sscanf( l, "%s%n", ipstr, &end) != 1) {
printf( "%d: parse error\n", line_no);
continue;
}
if ( sscanf( ipstr, "%u.%u.%u.%u", &ip1, &ip2, &ip3, &ip4) != 4) {
init_entry( 0, ipstr, NULL);
continue;
}
if ( (ip1&0xffffff00) || (ip2&0xffffff00) ||
(ip3&0xffffff00) || (ip4&0xffffff00)) {
printf( "%d: invalid IP address \"%s\"\n", line_no, ipstr);
continue;
}
ipaddr= (ip1<<24) | (ip2<<16) | (ip3<<8) | ip4;
entry= init_entry( ipaddr, NULL, NULL);
while ( 1) {
l+= end;
while ( isspace( *l)) l++;
if ( *l == '#' || *l == '\0')
break;
hostname[0]= '\0';
if ( sscanf( l, "%s%n", hostname, &end) != 1) {
printf( "%d: parse error\n", line_no);
continue;
}
init_entry( ipaddr, hostname, entry);
}
}
fclose(file);
return 0;
}
STATIC cache_entry *
init_entry( unsigned long ipaddr, char *hostname, cache_entry *known)
{
cache_entry *entry;
int e= 0, h;
if ( n_entry == max_entry) {
if ( max_entry == 0) {
max_entry= 50;
hcache= (cache_entry*) malloc(sizeof(cache_entry) * max_entry * 2);
}
else {
hcache= (cache_entry*) realloc( hcache,
sizeof(cache_entry) * max_entry * 2);
}
memset( hcache+n_entry, 0, sizeof(cache_entry) * max_entry *
(n_entry==0?2:1));
max_entry*= 2;
}
if ( ipaddr == 0) {
entry= find_host_entry( hostname);
if ( entry == NULL) {
hcache[n_entry].hostname[0]= strdup( hostname);
return &hcache[n_entry++];
}
return entry;
}
if ( known != NULL)
entry= known;
else {
for ( e= 0; e < n_entry; e++)
if ( hcache[e].ipaddr == ipaddr)
break;
entry= &hcache[e];
entry->ipaddr= ipaddr;
}
if ( hostname && hostname[0] != '\0') {
for ( h= 0; h < 5; h++)
if ( entry->hostname[h] == NULL) {
entry->hostname[h]= strdup( hostname);
break;
}
}
if ( e == n_entry)
n_entry++;
return entry;
}
STATIC cache_entry *
find_host_entry( char *hostname)
{
cache_entry *entry= &hcache[0];
char **ehost;
int e, h;
char first= *hostname;
for ( e= 0; e < n_entry; e++, entry++) {
ehost= &entry->hostname[0];
for ( h= 0; h < 5; h++, ehost++)
if ( *ehost && first == **ehost && strcmp( hostname, *ehost) == 0)
return entry;
}
return NULL;
}
void
hcache_write_file( char *filename)
{
FILE *file;
if ( filename != NULL)
file= fopen( filename, "w");
else
file= stdout;
if ( file == NULL) {
perror( filename);
return;
}
write_file( file);
}
void
hcache_update_file()
{
FILE *file;
if ( last_filename == NULL || n_changes == 0)
return;
file= fopen( last_filename, "w");
if ( file == NULL) {
perror( last_filename);
return;
}
write_file( file);
}
STATIC void
write_file( FILE *file)
{
int e, h;
for ( e= 0; e < n_entry; e++) {
unsigned long ipaddr= hcache[e].ipaddr;
if ( ipaddr == 0)
continue;
fprintf( file, "%u.%u.%u.%u", (ipaddr&0xff000000)>>24,
(ipaddr&0xff0000)>>16, (ipaddr&0xff00)>>8, ipaddr&0xff);
if ( hcache[e].hostname[0]) {
for ( h= 0; h < 5; h++)
if ( hcache[e].hostname[h] != NULL)
fprintf( file, "%c%s", h?' ':'\t', hcache[e].hostname[h]);
}
fprintf( file, "\n");
}
fclose( file);
}
void
hcache_invalidate()
{
int e, h;
for ( e= 0; e < n_entry; e++)
if ( hcache[e].ipaddr != 0)
memset( & hcache[e].hostname[0], 0, sizeof( hcache[e].hostname));
}
void
hcache_validate()
{
int e, h;
char **alias;
struct hostent *ent;
unsigned long ipaddr;
cache_entry *entry;
for ( e= 0; e < n_entry; e++) {
fprintf( stderr, "\r%d / %d validating ", e, n_entry);
if ( hcache[e].ipaddr != 0) {
ipaddr= hcache[e].ipaddr;
fprintf( stderr, "%u.%u.%u.%u", (ipaddr&0xff000000)>>24,
(ipaddr&0xff0000)>>16, (ipaddr&0xff00)>>8, ipaddr&0xff);
ipaddr= htonl( ipaddr);
ent= gethostbyaddr( (char*)&ipaddr, sizeof(unsigned long),
AF_INET);
}
else if ( hcache[e].hostname[0] != NULL) {
fprintf( stderr, "%s", hcache[e].hostname[0]);
ent= gethostbyname( hcache[e].hostname[0]);
if ( ent != NULL) {
memcpy( &ipaddr, ent->h_addr_list[0], sizeof(ipaddr));
ipaddr= ntohl( ipaddr);
if ( (entry= find_entry( ipaddr)) != NULL) {
add_hostname( entry, hcache[e].hostname[0]);
free_entry( &hcache[e]);
}
else
hcache[e].ipaddr= ipaddr;
}
}
else
continue;
if ( ent == NULL)
continue;
if ( ent->h_name && ent->h_name[0] != '\0')
add_hostname( &hcache[e], ent->h_name);
printf( "h_name %s\n", ent->h_name?ent->h_name:"NULL");
alias= ent->h_aliases;
while ( *alias) {
add_hostname( &hcache[e], *alias);
printf( "h_aliases %s\n", *alias);
alias++;
}
}
}
STATIC cache_entry *
validate_entry( cache_entry *entry)
{
struct hostent *ent;
char **alias;
cache_entry *tmp;
unsigned long ipaddr;
if ( entry->ipaddr != 0) {
ipaddr= htonl( entry->ipaddr);
/* fprintf( stderr, "%u.%u.%u.%u", (ipaddr&0xff000000)>>24,
(ipaddr&0xff0000)>>16, (ipaddr&0xff00)>>8, ipaddr&0xff);
*/
ent= gethostbyaddr( (char*)&ipaddr, sizeof(unsigned long), AF_INET);
}
else if ( entry->hostname[0] != NULL) {
/* fprintf( stderr, "%s", entry->hostname[0]);
*/
ent= gethostbyname( entry->hostname[0]);
if ( ent != NULL) {
memcpy( &ipaddr, ent->h_addr_list[0], sizeof(ipaddr));
ipaddr= ntohl( ipaddr);
if ( (tmp= find_entry( ipaddr)) != NULL) {
add_hostname( tmp, entry->hostname[0]);
free_entry( entry);
entry= tmp;
}
else
entry->ipaddr= ipaddr;
}
}
else
return NULL;
if ( ent == NULL)
return NULL;
if ( ent->h_name && ent->h_name[0] != '\0')
add_hostname( entry, ent->h_name);
alias= ent->h_aliases;
while ( *alias) {
add_hostname( entry, *alias);
alias++;
}
return entry;
}
unsigned long
hcache_lookup_hostname( char *hostname)
{
cache_entry *entry;
int e, h;
if ( debug) printf( "looking up %s\n", hostname);
for ( e= 0; e < n_entry; e++) {
for ( h= 0; h < 5; h++) {
if ( hcache[e].hostname[h] &&
strcmp( hostname, hcache[e].hostname[h]) == 0)
return hcache[e].ipaddr;
}
}
entry= init_entry( 0, hostname, NULL);
if ( entry->ipaddr == 0) {
if ( debug) printf( "validating %s\n", hostname);
entry= validate_entry( entry);
n_changes++;
}
if ( debug) printf( "returning %x\n", entry->ipaddr);
if ( entry != NULL && entry->ipaddr)
return entry->ipaddr;
return INADDR_NONE;
}
char *
hcache_lookup_ipaddr( unsigned long ipaddr)
{
cache_entry *entry;
int e;
for ( e= 0; e < n_entry; e++)
if ( hcache[e].ipaddr == ipaddr)
return hcache[e].hostname[0];
entry= init_entry( ipaddr, 0, NULL);
if ( debug) printf( "validating %x\n", ipaddr);
validate_entry( entry);
n_changes++;
return entry ? entry->hostname[0] : NULL;
}
STATIC cache_entry *
find_entry( unsigned long ipaddr)
{
int e;
for ( e= 0; e < n_entry; e++)
if ( hcache[e].ipaddr == ipaddr)
return &hcache[e];
return NULL;
}
STATIC void
free_entry( cache_entry *entry)
{
int h;
for ( h= 0; h < 5; h++)
if ( entry->hostname[h] != NULL)
free( entry->hostname[h]);
memset( entry, 0, sizeof(*entry));
}
STATIC void
add_hostname( cache_entry *entry, const char *hostname)
{
int h;
for ( h= 0; h < 5; h++) {
if ( entry->hostname[h] == NULL)
break;
if ( strcmp( entry->hostname[h], hostname) == 0)
return;
}
if ( h < 5)
entry->hostname[h]= strdup( hostname);
}
/*
main(int argc, char *argv[])
{
hcache_open( argv[1], 0);
hcache_write(NULL);
hcache_invalidate();
printf( "invalidate\n");
hcache_write(NULL);
hcache_validate();
printf( "validate\n");
hcache_write( "/tmp/qhcache.out");
}
*/